package com.ict.ycwl.pathcalculate.utils;

import com.ict.ycwl.pathcalculate.pojo.LngAndLat;

import javax.xml.crypto.dsig.keyinfo.KeyName;
import java.util.ArrayList;
import java.util.List;

public class FindNearestBoundaryPoint {
    // 计算两个经纬度坐标点之间的距离（使用球面余弦定理）
    private static double distanceBetweenPoints(LngAndLat point1, LngAndLat point2) {
        double lat1 = Math.toRadians(point1.getLatitude());
        double lon1 = Math.toRadians(point1.getLongitude());
        double lat2 = Math.toRadians(point2.getLatitude());
        double lon2 = Math.toRadians(point2.getLongitude());

        // 使用球面余弦定理计算距离
        double cosDistance = Math.sin(lat1) * Math.sin(lat2) + Math.cos(lat1) * Math.cos(lat2) * Math.cos(lon2 - lon1);
        // 6371 是地球的半径（单位：公里）
        return Math.acos(cosDistance) * 6371;
    }

    // 找到点到边界点集合中最近的点
    private static LngAndLat findNearestBoundaryPoint(LngAndLat point, List<LngAndLat> boundaryPoints) {
        LngAndLat nearestBoundaryPoint = null;
        double minDistance = Double.MAX_VALUE;

        for (LngAndLat l : boundaryPoints) {
            double distance = distanceBetweenPoints(point, l);
            if (distance < minDistance) {
                minDistance = distance;
                nearestBoundaryPoint = l;
            }
        }

        return nearestBoundaryPoint;
    }

    public static LngAndLat find(LngAndLat point1, LngAndLat point2, List<LngAndLat> boundaryPoints, LngAndLat center) {
        // 计算 point1 到边界点集合中每个点的距离，并找到最近的边界点
        LngAndLat nearestBoundaryPoint1 = findNearestBoundaryPoint(point1, boundaryPoints);
        // 计算 point2 到边界点集合中每个点的距离，并找到最近的边界点
        LngAndLat nearestBoundaryPoint2 = findNearestBoundaryPoint(point2, boundaryPoints);
        // 比较哪个点更接近边界点集合
        double distance1 = distanceBetweenPoints(point1, nearestBoundaryPoint1);
        double distance2 = distanceBetweenPoints(point2, nearestBoundaryPoint2);
        //选择更近的那一组点中的边界点，进行返回
        if (distance1 < distance2) {
            return nearestBoundaryPoint1;
        } else if (distance2 < distance1) {
            return nearestBoundaryPoint2;
        } else {
            //如果走到这，意味着两组距离相等，则选择point1和point2中，离这个班组的中心点更远的那一组
            double v1 = distanceBetweenPoints(point1, center);
            double v2 = distanceBetweenPoints(point2, center);
            if (v1 > v2) {
                return nearestBoundaryPoint1;
            } else {
                return nearestBoundaryPoint2;
            }
        }
    }

    public static ArrayList<LngAndLat> find(List<LngAndLat> filteredSplitLines, List<LngAndLat> boundaryPoints, LngAndLat center) {
        double max = Double.MAX_VALUE;
        LngAndLat result = null;
        LngAndLat linesPoint = null;
        for(LngAndLat l : filteredSplitLines){
            // 计算 当前点 到边界点集合中每个点的距离，并找到最近的边界点
            LngAndLat nearestBoundaryPoint = findNearestBoundaryPoint(l, boundaryPoints);
            // 看看是否更接近边界点集合
            double distance = distanceBetweenPoints(l, nearestBoundaryPoint);
            //选择更近的那一组点中的边界点，进行返回
            if (distance < max) {
                max = distance;
                result = nearestBoundaryPoint;
                linesPoint = l;
            }
        }
        ArrayList<LngAndLat> a = new ArrayList<>();
        a.add(linesPoint);
        a.add(result);
        return a;
    }
}
